#pragma once
#include <string>
#include <unordered_map>
#include <regex>

namespace Http
{
    //Http请求
    class HttpRequest
    {
    public:
        HttpRequest():_version("HTTP/1.1"){}
        //处理完请求,重置一下
        void ReSet()
        {
            _method.clear();
            _path.clear();
            _version = "HTTP/1.1";
            _body.clear();
            std::smatch match;
            _matches.swap(match);
            _headers.clear();
            _params.clear();
        }

        //插入头部字段
        void SetHeader(const std::string & key,const std::string & val)
        {
            _headers.insert(std::make_pair(key,val));
        }

        //判断是否存在指定头部字段
        bool HasHeader(const std::string & key) const
        {
            auto it = _headers.find(key);
            if(it == _headers.end())
            {
                return false;
            }
            return true;
        }

        //获取指定头部字段的值
        std::string GetHeader(const std::string &key) const
        {
            auto it = _headers.find(key);
            if(it == _headers.end())
            {
                return "";
            }
            return it->second;
        }

        //插入查询字符串
        void SetParam(const std::string & key,const std::string & val)
        {
            _params.insert(std::make_pair(key,val));
        }

        //判断是否有某个指定的查询字符串
        bool HasParam(const std::string & key)
        {
            auto it = _params.find(key);
            if(it == _params.end())
            {
                return false;
            }
            return true;
        }

        //获取指定的查询字符串
        std::string GetParams(const std::string & key)
        {
            auto it = _params.find(key);
            if(it == _params.end())
            {
                return "";
            }
            return it->second;
        }

        //获取正文长度
        size_t ContentLength()
        {
            bool ret = HasHeader("Content-Length");
            if(ret == false)
            {
                return 0;
            }
            std::string clen = GetHeader("Content-Length");
            return std::stoul(clen);
        }

        //判断是否是短连接
        bool Close() const
        {
            if(HasHeader("Connection")&&GetHeader("Connection") == "keep-alive")
            {
                return false;
            }
            return true;
        }

    public:
        std::string _method;//请求方法
        std::string _path;//资源路径
        std::string _version;//协议版本
        std::string _body;//请求正文
        std::smatch _matches;//资源路径的正则提取数据
        std::unordered_map<std::string,std::string> _headers;//头部字段
        std::unordered_map<std::string,std::string> _params;//查询字符串
    };

    //Http响应
    class HttpResponse
    {
    public:
        HttpResponse():_redirect_flag(false),_statu(200){}
        HttpResponse(int statu):_redirect_flag(false),_statu(statu){}
        //重置
        void ReSet()
        {
            _statu = 200;
            _redirect_flag = false;
            _body.clear();
            _redirect_url.clear();
            _headers.clear();
        }

        //插入头部字段
        void SetHeader(const std::string & key,const std::string & val)
        {
            _headers.insert(std::make_pair(key,val));
        }

        //判断是否存在指定头部字段
        bool HasHeader(const std::string & key) 
        {
            auto it = _headers.find(key);
            if(it == _headers.end())
            {
                return false;
            }
            return true;
        }

        //获取指定头部字段的值
        std::string GetHeader(const std::string &key)
        {
            auto it = _headers.find(key);
            if(it == _headers.end())
            {
                return "";
            }
            return it->second;
        }

        //设置正文
        void SetContent(const std::string & body,const std::string & type = "text/html")
        {
            _body = body;
            SetHeader("Content-Type",type);
        }

        //设置重定向
        void SetRedirect(const std::string & url,int statu = 302)
        {
            _statu = statu;
            _redirect_flag = true;
            _redirect_url = url;
        }

        //判断是否是短连接
        bool Close()
        {
            if(HasHeader("Connection")&&GetHeader("Connection") == "keep-alive")
            {
                return false;
            }
            return true;
        }

    public:
        int _statu;//响应状态码
        bool _redirect_flag;//是否重定向
        std::string _body;//响应正文
        std::string _redirect_url;//重定向的url
        std::unordered_map<std::string,std::string> _headers;//头部字段
    };
}